package saves.objects;

import game.Units;
import images.ImageInfo;
import images.ObjectLoader;
import java.awt.Color;
import java.io.Serializable;
import menu.Menu;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.World;
import saves.Area;
import saves.EntidadeNave;

public class Corpo implements Serializable {

    private static final long serialVersionUID = 3025733891561328035L;
    
    //if it is the original area, we use the body; otherwise, only the x and y coordinates are saved
    protected transient Body body;
    protected float x, y;
    
    protected int codImagem;
    private transient boolean collided;
    private transient Corpo collision;
    private long destruir;

    protected Corpo() {}
    
    public Corpo(float x, float y, int codImagem, World world) {
        this(x, y, codImagem, BodyType.KINEMATIC, world);
    }
    
    public Corpo(float x, float y, int codImagem, BodyType type, World world) {
        this(x, y, 0, codImagem, type, world);
    }
    
    public Corpo(float x, float y, float angle, int codImagem, BodyType type, World world) {
        //body definition
        BodyDef bd = new BodyDef();
        bd.position.set(x, y);
        bd.type = type;
        bd.angle = angle;
        bd.userData = this;

        //create the body and add fixture to it
        this.body = world.createBody(bd);
        this.body.setBullet(true);
        if (codImagem != -1)
            this.body.createFixture(ObjectLoader.getFixture(codImagem));
        //else must be done internally by each subclass

        this.codImagem = codImagem;
        this.destruir = -1;
    }
    
    public float getRealX() {
        if (body == null)
            return this.x;
        return body.getPosition().x;
    }

    public float getRealY() {
        if (body == null)
            return this.y;
        return body.getPosition().y;
    }
    
    public int getPixelX() {
        return Units.getPixelSize(getRealX());
    }
    
    public int getPixelY() {
        return Units.getPixelSize(getRealY());
    }

    public boolean paraDestruir() {
        return this.destruir == 0;
    }

    public void setDestruir() {
        this.destruir = 0;
    }
    
    public void setDestruir(long ms) {
        this.destruir = ms;
    }
    
    //in pixels!!
    public double dist(Corpo m) {
        return Math.sqrt(Math.pow(m.getPixelX() - this.getPixelX(), 2) + Math.pow(m.getPixelY() - this.getPixelY(), 2));
    }
    
    //in reality 
    public double dist(float x, float y) {
        return Math.sqrt(Math.pow(x - this.getRealX(), 2) + Math.pow(y - this.getRealY(), 2));
    }
    
    public void updateCache() {
        this.x = getRealX();
        this.y = getRealY();
    }
    
    //to be overwriter
    public void update(int delta, Area a) {
        if (destruir > 0)
            destruir--;
        if (collided) {
            onCollide(a, collision);
            collided = false;
        }
    }
    
    public void harm(float power, EntidadeNave.DamageType type, EntidadeNave origem) { }
    
    protected void onCollide(Area a, Corpo c) {}
    
    public void collided(Corpo c) {
        this.collided = true;
        this.collision = c;
    }
    
    public int getPixelWidth() {
        return ObjectLoader.getObjectWidth(codImagem);
    }
    
    public int getPixelHeight() {
        return ObjectLoader.getObjectHeight(codImagem);
    }
    
    public float getRealAngle() {
        return body.getAngle();
    }
    
    public float getDrawingAngle() {
        float ang = ((float) Math.toDegrees(body.getAngle()) + 90) % 360;
        while (ang < 0)
            ang += 360;
        return ang;
    }

    public Body getBody() {
        return body;
    }
    
    //this is for the actual game, regular size, rotated
    public void draw(int dx, int dy) {
        int ox = getPixelX() - dx, oy = getPixelY() - dy;
        ObjectLoader.drawObject(codImagem, ox + getPixelWidth()/2, oy + getPixelHeight()/2, this.getDrawingAngle());
    }
    
    //this is for reference propuses, resized, not rotated
    public void draw(int x, int y, int w, int h) {
        ObjectLoader.bindObjects();
        ObjectLoader.drawObject(codImagem, x, y, w, h);
    }
    
    public void drawSelector(int ox, int oy) {
        ImageInfo.drawOctagon(ox - 5, oy - 5, this.getPixelWidth() + 10, this.getPixelHeight() + 10, Color.WHITE, 10);
    }
    
    public static void drawHolder(int x, int y) {
        ImageInfo.drawColorSquare(x - 2, y - 2, 4, 4, Color.BLUE);
    }
    
    public boolean isSelectable() {
        return true;
    }
    
    public String[] getInterfaces() {
        return new String[0];
    }
    
    public Menu getInterface(int cod, EntidadeNave p) {
        return null;
    }
    
    public String getDescription() {
        return toString();
    }
}
